﻿using System;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System.Runtime.InteropServices;

namespace Com.SqlSmarts.SSDTPrettySave
{
    public class DocTableEventsListner : IVsRunningDocTableEvents3, IDisposable
    {
        // IVsRunningDocumentTable _runningDocTable;
        //private uint _runningDocTableEventsCookie;

        private IVsRunningDocumentTable _runningDocumentTable;
        private uint _runningDocTableEventsCookie;


        public event Action OnAfterFirstDocumentLock;
        public event Action OnBeforeLastDocumentUnlock;
        public event Action<string, IVsPersistDocData> OnAfterSave;
        public event Action OnAfterAttributeChange;
        public event Action OnBeforeDocumentWindowShow;
        public event Action OnAfterDocumentWindowHide;


        public DocTableEventsListner()
        {
            InitNullEvents();
            _runningDocumentTable = (IVsRunningDocumentTable)Package.GetGlobalService(typeof(SVsRunningDocumentTable));

            if (_runningDocumentTable != null)
            {
                _runningDocumentTable.AdviseRunningDocTableEvents(this, out _runningDocTableEventsCookie);
            }
        }

        private void InitNullEvents()
        {
            OnAfterFirstDocumentLock += () => { };
            OnBeforeLastDocumentUnlock += () => { };
            OnAfterSave += (filename, docData) => { };
            OnAfterAttributeChange += () => { };
            OnBeforeDocumentWindowShow += () => { };
            OnAfterDocumentWindowHide += () => { };

        }

        int IVsRunningDocTableEvents.OnAfterFirstDocumentLock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining)
        {
            if (OnAfterFirstDocumentLock != null)
                OnAfterFirstDocumentLock();
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents.OnBeforeLastDocumentUnlock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining)
        {
            if (OnBeforeLastDocumentUnlock != null)
                OnBeforeLastDocumentUnlock();
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents.OnAfterSave(uint docCookie)
        {
            uint flags,
                 readlocks,
                 editlocks;
            string name;
            IVsHierarchy hier;
            uint itemid;
            IntPtr docDataPtr;
            var info = _runningDocumentTable.GetDocumentInfo(docCookie, out flags, out readlocks, out editlocks, out name, out hier, out itemid, out docDataPtr);

            var docData = Marshal.GetObjectForIUnknown(docDataPtr) as IVsPersistDocData;

            if (OnAfterSave != null)
                OnAfterSave(name, docData);

            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents.OnAfterAttributeChange(uint docCookie, uint grfAttribs)
        {
            if (OnAfterAttributeChange != null)
                OnAfterAttributeChange();
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents.OnBeforeDocumentWindowShow(uint docCookie, int fFirstShow, IVsWindowFrame pFrame)
        {
            if (OnBeforeDocumentWindowShow != null)
                OnBeforeDocumentWindowShow();
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents.OnAfterDocumentWindowHide(uint docCookie, IVsWindowFrame pFrame)
        {
            if (OnAfterDocumentWindowHide != null)
                OnAfterDocumentWindowHide();
            return VSConstants.S_OK;
        }

        public void Dispose()
        {
            if (_runningDocumentTable == null || _runningDocTableEventsCookie == 0)
                return;

            GC.SuppressFinalize(this);
            _runningDocumentTable.UnadviseRunningDocTableEvents(_runningDocTableEventsCookie);
            OnAfterFirstDocumentLock = null;
            OnBeforeLastDocumentUnlock = null;
            OnAfterSave = null;
            OnAfterAttributeChange = null;
            OnBeforeDocumentWindowShow = null;
            OnAfterDocumentWindowHide = null;
            _runningDocTableEventsCookie = 0;
            _runningDocumentTable = null;
        }



        int IVsRunningDocTableEvents3.OnAfterAttributeChangeEx(uint docCookie, uint grfAttribs, IVsHierarchy pHierOld, uint itemidOld, string pszMkDocumentOld, IVsHierarchy pHierNew, uint itemidNew, string pszMkDocumentNew)
        {
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents3.OnBeforeSave(uint docCookie)
        {
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents2.OnAfterAttributeChange(uint docCookie, uint grfAttribs)
        {
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents2.OnAfterAttributeChangeEx(uint docCookie, uint grfAttribs, IVsHierarchy pHierOld, uint itemidOld, string pszMkDocumentOld, IVsHierarchy pHierNew, uint itemidNew, string pszMkDocumentNew)
        {
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents2.OnAfterDocumentWindowHide(uint docCookie, IVsWindowFrame pFrame)
        {
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents2.OnAfterFirstDocumentLock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining)
        {
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents2.OnAfterSave(uint docCookie)
        {
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents2.OnBeforeDocumentWindowShow(uint docCookie, int fFirstShow, IVsWindowFrame pFrame)
        {
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents2.OnBeforeLastDocumentUnlock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining)
        {
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents3.OnAfterAttributeChange(uint docCookie, uint grfAttribs)
        {
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents3.OnAfterDocumentWindowHide(uint docCookie, IVsWindowFrame pFrame)
        {
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents3.OnAfterFirstDocumentLock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining)
        {
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents3.OnAfterSave(uint docCookie)
        {
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents3.OnBeforeDocumentWindowShow(uint docCookie, int fFirstShow, IVsWindowFrame pFrame)
        {
            return VSConstants.S_OK;
        }

        int IVsRunningDocTableEvents3.OnBeforeLastDocumentUnlock(uint docCookie, uint dwRDTLockType, uint dwReadLocksRemaining, uint dwEditLocksRemaining)
        {
            return VSConstants.S_OK;
        }
    }
}
